package at.fhv.androideightpuzzle.network;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import at.fhv.androideightpuzzle.application.IObserverArguments;
import at.fhv.androideightpuzzle.application.MultiPlayerHostController;

public class TcpServerSocket extends NetworkServerSocket{
	
	private ServerSocket m_serverSocket;
	private AcceptRunnable m_acceptRunnable;
	
	private Thread m_acceptThread;
	
	private NetworkServerSocket m_selfReference;
	
	public TcpServerSocket(){
		super(ConnectionType.TCP);
		
		m_serverSocket=null;
		m_acceptRunnable=null;
		m_acceptThread=null;
		
		m_selfReference=this;
	}
	
	@Override
	public void startAccepting() throws IOException{
		startAccepting(INetworkConstants.TCP_PORT);
	}
	
	public void startAccepting(int port) throws IOException{
		try {
			//m_serverSocket=new ServerSocket(port);
			
			m_acceptRunnable=new AcceptRunnable(port);
			m_acceptThread=new Thread(m_acceptRunnable);
			m_acceptThread.start();
		}catch(/*IO*/Exception exc){
			android.util.Log.e("TcpServerSocket",exc.getMessage(),exc);
			
			//throw exc;
		}
	}
	
	@Override
	public void stopAccepting() throws IOException{
		if(m_serverSocket!=null){
			android.util.Log.d("TcpServerSocket.AcceptRunnable","Stop accepting clients");
			//
			try{
				m_acceptRunnable.stop();
				
				m_acceptThread.interrupt();
				
				m_serverSocket.close();
			}catch(IOException exc){
				android.util.Log.e("TcpServerSocket",exc.getMessage(),exc);
				
				throw exc;
			}
		}
	}
	
	private class AcceptRunnable implements Runnable{
		
		private int m_port;
		
		private boolean m_stopFlag;
		
		public AcceptRunnable(int port){
			m_port=port;
			
			m_stopFlag=false;
		}
		
		public void run(){
			android.util.Log.d("TcpServerSocket.AcceptRunnable","Start to listen for connections...");
			//
			try{
				m_serverSocket=new ServerSocket(m_port);
				//
				android.util.Log.d("TcpServerSocket.AcceptRunnable","ServerSocket created at port "+m_port);
				//
				
				while(!m_stopFlag){
					Socket socket=m_serverSocket.accept();
					
					//
					android.util.Log.d("TcpServerSocket.AcceptRunnable","Client accepted");
					//
					
					if(socket!=null){
						TcpSocket tcpSocket=new TcpSocket();
						tcpSocket.setSocket(socket);
						tcpSocket.addObserver(m_selfReference);
						tcpSocket.addObserver(MultiPlayerHostController.getInstance());
						
						//synchronized(m_clients){
							m_clients.add(tcpSocket);
						//}
						
						setChanged();
						notifyObservers(IObserverArguments.CLIENT_JOINED);
					}
				}
				//
				android.util.Log.d("TcpServerSocket.AcceptRunnable","Stop listening...");
			}catch(IOException exc){
				android.util.Log.e("TcpServerSocket.AcceptRunnable",exc.getMessage(),exc);
				
				m_stopFlag=true;
			}
		}
		
		public void stop(){
			m_stopFlag=true;
		}
	}
}
